package com.itbaizhan.service.impl;

import com.alibaba.dubbo.config.annotation.Reference;
import com.itbaizhan.pojo.CommonResult;
import com.itbaizhan.pojo.Orders;
import com.itbaizhan.service.IOrderService;
import com.itbaizhan.service.IUserService;
import org.springframework.stereotype.Service;

/*实现用户接口
* 远程调用，消费层要调用生产者层的接口*/
@Service  //这个是spring 的包
public class UserServiceImpl implements IUserService {
    /*引入订单服务，生产者层的接口
    * 远程调用
    * @Autowired 本地调用
    * @Reference  导入含有dubbo 的包 1，从zookeeper 注册中心获取IOrderService 访问的URL
    * 2,进行远程调用RPC  调用生产层的接口，拿到序列化的数据
    * 3,将结果封装为一个代理对象，交给这个变量赋值*/
    //loadbalance = "roundrobin" 负载均衡
/*andom：随机负载均衡
leastactive：最少活跃调用数，相同活跃数的随机
roundrobin：轮询负载均衡
consistenthash：一致性哈希负载均衡*/
    //@Reference(version = "*")  不需要区分版本
    //集群容错模式  cluster = "Failover"
   // @Reference(loadbalance = "roundrobin",cluster = "Failover")
    //lru:基于最近最少使用原则删除多佘缓存，保持最热的数据缓存
    //threadlocal:当前线程缓存
    //jcache: 与JSR107集成，可以桥接各种缓存实现。
    //@Reference(cache = "lru")
    @Reference
    private IOrderService iOrderService;
    @Override
    public CommonResult findByUserId(Long id) {

       // 远程调用
        CommonResult<Orders> ordersCommonResult = iOrderService.findUserId(id);

        return ordersCommonResult;
    }
}
/*远程调用   修改producer还是修改consumer 重启其中一个项目就可以，不用两个都重启
* 在producer层用注解@Service(导入含dubbo的包)，把接口实现类注册到zookeeper的注册中心，
* 在consumer层的接口实现类中使用注解@Reference 从注册中心拿到序列化数据*/

/*度发布(金丝雀发布)：

当出现新功能时，会让一部分用户先使用新功能，用户反馈没问题时，再将所有用户迁移到新功能。

版本迁移步骤
在低压力时间段，先升级一半提供者为新版本
再将所有消费者升级为新版本
然后将剩下的一半提供者升级为新版本
老版本服务提供者配置
@Service(version = "1.0.0")
public class OrderServiceImpl implements IOrderService {

新版本服务提供者配置
@Service(version = "2.0.0")
public class OrderServiceImpl implements IOrderService {

新版本服务消费者配置
@Reference(version = "2.0.0")
private IOrderService iOrderService;// 订单服务
*/


/*Dubbo高级特性_负载均衡
* Dubbo是一个分布式服务框架，能避免单点故障和支持服务的横向扩容。一个服务通常会部署多个实例。
* 问题：

订单服务生产者会出现单点故障。

何从多个服务 Provider 组成的集群中挑选出一个进行调用，就涉及到一个负载均衡的策略。

Dubbo内置负载均衡策略
RandomLoadBalance：随机负载均衡，随机的选择一个，默认负载均衡。
RoundRobinLoadBalance：轮询负载均衡。
LeastActiveLoadBalance：最少活跃调用数，相同活跃数的随机。
ConsistentHashLoadBalance：一致性哈希负载均衡，相同参数的请求总是落在同一台机器上。
负载均衡策略配置
如果不指定负载均衡，默认使用随机负载均衡。我们也可以根据自己的需要，显式指定一个负载均衡。

生产者服务
@Service(timeout = 3000,retries = 3,loadbalance = "roundrobin")
*
* 在消费端配置就可以，不用在生产者配置，请求是有consumber去发出的，并不是provider发出的。
消费者服务
@Reference(timeout = 2000,loadbalance = "roundrobin"
参数：

random：随机负载均衡(默认)
leastactive：最少活跃调用数，相同活跃数的随机
roundrobin：轮询负载均衡
consistenthash：一致性哈希负载均衡
* */

/*集群容错模式
Dubbo框架为服务集群容错提供了一系列好的解决方案，在此称为dubbo服务集群容错模式。
容错模式
Failover Cluster：失败重试。默认值。当出现失败，重试其它服务器，默认重试2次，使用retries配置。一般用于读操作
Failfast Cluster : 快速失败，只发起一次调用，失败立即报错。通常用于写操作。
Failsafe Cluster : 失败安全，出现异常时，直接忽略。返回一个空结果。日志不重要操作。
Failback Cluster : 失败自动恢复，后台记录失败请求，定时重发。非常重要的操作。
Forking Cluster：并行调用多个服务器，只要有一个成功即返回。
Broadcast Cluster：广播调用所有提供者，逐个调用，任意一台报错则报错。 同步要求高的可以使用这个模式。
集群容错配置
在消费者服务配置

@Reference(cluster = "failover")
private IOrderService iOrderService;*/

/*什么是服务降级
服务降级，当服务器压力剧增的情况下，根据当前业务情况及流量对一些服务和
页面有策略的降级，以此释放服务器资源以保证核心任务的正常运行。

两种场景：

当下游的服务因为某种原因响应过慢，下游服务主动停掉一些不太重要的业务，释放出服务器资源，增加响应速度！
当下游的服务因为某种原因不可用，上游主动调用本地的一些降级逻辑，避免卡顿，迅速返回给用户！

为什么需要降级
当访问量剧增、服务出现问题（如响应时间慢或不响应）或非核心服务影响到核心流程的性能时，仍然需要保证服务还是可用的，即使是有损服务。

服务降级方式
第一种
mock=force:return null
含义：

表示消费方对该服务的方法调用都直接返回null值，不发起远程调用。用来屏蔽不重要服务不可用时对调用方的影响。

第二种
mock=fail:return null
含义：

表示消费方对该服务的方法调用在失败后，再返回null值，不抛异常。用来容忍不重要服务不稳定时对调用方的影响。

服务降级演示
@Reference(timeout = 2000,mock = "force:return null")
private IOrderService iOrderService;*/